<template>
	<div class="containers">
		<div ref="canvas" class="canvas" />
		<div id="js-properties-panel" class="properties-panel-parent" />
		<div class="buttons">
			<input v-show="false" ref="fileInput" type="file" accept=".bpmn" @change="getFile" />
			<el-button icon="el-icon-folder-opened" type="primary" plain @click="openDiagram">打开bpmn文件</el-button>
			<el-button icon="el-icon-download" type="primary" plain @click="saveDiagram">BPMN diagram</el-button>
			<el-button icon="el-icon-picture" type="primary" plain @click="saveSvg">SVG图片</el-button>
			<el-button icon="el-icon-picture" type="primary" plain @click="localBpmn">log</el-button>
			<el-button type="primary" size="mini" @click="handleUndo">后退</el-button>
			<el-button type="success" size="mini" @click="handleRedo">前进</el-button>
			<el-button type="success" size="mini" @click="zoom(0.1)">放大</el-button>
			<el-button type="success" size="mini" @click="zoom(-0.1)">缩小</el-button>
			<el-button type="success" size="mini" @click="zoom(0)">还原</el-button>
			<el-button type="success" size="mini" @click="clear">清空</el-button>
		</div>
	</div>
</template>

<script>
/* eslint-disable */
import BpmnViewer from "bpmn-js/lib/Viewer"; // 这个为预览，只需配置container
import Modeler from "bpmn-js/lib/Modeler"; // 引入流程图
import propertiesPanelModule from "bpmn-js-properties-panel"; //  这里引入的是右侧属性栏这个框
import propertiesProviderModule from "bpmn-js-properties-panel/lib/provider/camunda"; // 而这个引入的是右侧属性栏里的内容
import zhCN from "./customTranslate"; // 中文
import camundaModdleDescriptor from "camunda-bpmn-moddle/resources/camunda"; // 外部任务配置
import { xmlStr } from "./mock/xmlStr";
export default {
	data() {
		return {
			modeler: null,
		};
	},
	mounted() {
		// 生成实例
		this.modeler = new Modeler({
			container: this.$refs.canvas,
			keyboard: {
				// 快捷键
				bindTo: window, // document
			},
			width: "100%",
			height: "100%",
			propertiesPanel: {
				parent: "#js-properties-panel",
			},
			bpmnRenderer: {
				defaultFillColor: "#fff",
				defaultStrokeColor: "teal",
			},
			textRenderer: {
				defaultStyle: {
					// fontFamily: '"Nothing You Could Do"',
					// fontWeight: 'bold',
					// fontSize: 12,
					// lineHeight: 16
				},
				externalStyle: {
					// fontSize: 12,
					// lineHeight: 1
				},
			},
			additionalModules: [
				// 自定义且与默认扩展包一起使用的模块列表
				propertiesPanelModule, // 右边工具栏
				propertiesProviderModule, // 右边的工具栏
				{
					translate: ["value", zhCN], // 中文
					// zoomScroll: ["value", ""],// 禁用滚轮滚动
					// bendpoints: ["value", ""], // 禁止拖动线
					// paletteProvider: ["value", ""], // 禁用左侧面板
					// contextPadProvider: ["value", ""],// 禁止点击节点出现contextPad
					// labelEditingProvider: ["value", ""] // 禁止双击节点出现label编辑框
				},
			],
			moddleExtensions: {
				// 需要用的扩展包
				camunda: camundaModdleDescriptor,
			},
		});

		console.log(this.modeler);
		this.createNewDiagram(); // 新增流程定义
		this.bpmnEvent();
	},
	beforeDestroy() {
		this.modeler.destroy();
	},
	methods: {
		// 注册节点事件，可以写多个事件
		bpmnEvent() {
			const eventBus = this.modeler.get("eventBus");
			eventBus.on(["element.click", "element.changed"], e => {
				const { element, type } = e;
				// console.log(eventType, element);
				if (!e || !element || !element.parent || element.type === "bpmn:Process") return; // 这里我的根元素是bpmn:Process
				if (type === "element.click") {
					console.log(element);
					// this.changeColor(element)
					// this.overlays(element)
					// this.changeAttrs(element)
					this.addMarker(element);
				} else if (type === "element.hover") {
					// 鼠标滑过节点后想要做的处理
					// console.log("鼠标经过节点啦~");
				} else if (type === "element.changed") {
					console.log("元素改变触发");
				}
			});
		},
		// 给图绑定事件，当图有发生改变就会触发这个事件
		addBpmnListener() {
			const that = this;
			this.modeler.on("commandStack.changed", function () {
				// that.saveDiagram(function (err, xml) {
				//   console.log(xml) // 这里获取到的就是最新的xml信息
				// })
			});
		},
		// 叠加元素
		overlays(element) {
			let overlays = this.modeler.get("overlays");
			let overlayHtml = document.createElement("div");
			overlayHtml.innerHTML = "Mixed up the labels?";

			// 添加
			const overlayId = overlays.add(element, {
				position: {
					bottom: 0,
					right: 0,
				},
				html: overlayHtml,
			});

			// 移除
			overlayHtml.onclick = function (e) {
				alert("someone clicked me");
				overlays.remove(overlayId);
			};
		},
		// 改变属性
		changeAttrs(element) {
			let modeling = this.modeler.get("modeling");
			modeling.updateProperties(element, { id: "a110" });
		},
		// 添加类名
		addMarker(element) {
			this.modeler.get("canvas").addMarker(element.id, "addMarker-class");
		},
		// 元素颜色
		changeColor(element) {
			let modeling = this.modeler.get("modeling");
			modeling.setColor([element], {
				stroke: "green",
				fill: "yellow",
			});
			// modeling.setColor([element], null); // removing previously set colors
		},
		// 后退
		handleUndo() {
			this.modeler.get("commandStack").undo();
		},
		// 前进
		handleRedo() {
			this.modeler.get("commandStack").redo();
		},
		// 放大缩小
		zoom(num) {
			const newScale = !num ? 1.0 : this.modeler.get("canvas").zoom() + num;
			this.modeler.get("canvas").zoom(newScale);
		},
		localBpmn() {
			console.log(this.modeler);
			console.log(propertiesProviderModule);
			this.modeler.saveXML((err, xml) => {
				console.log(err);
				console.log(xml);
				sessionStorage.setItem("xml", xml);
			});
		},
		// 新增流程定义
		async createNewDiagram() {
			// this.modeler.createDiagram()//创建空白流程图
			// 自定义的xml模板，可以自己修改
			const xml = sessionStorage.getItem("xml");
			try {
				const result = await this.modeler.importXML(xmlStr || xml);
				const { warnings } = result;
				console.log("success !", warnings);
				this.addBpmnListener();
				this.modeler.get("canvas").zoom("fit-viewport", "auto"); // 画布剧中
			} catch (err) {
				const { warnings, message } = err;
				console.log("something went wrong:", warnings, message);
			}
		},
		// 打开本地文件，调用input的click事件
		openDiagram() {
			this.$refs.fileInput.click();
		},
		// 打开本地文件
		getFile(e) {
			this.fileList = e.target.files || [];
			if (this.fileList.length === 0) return;
			const reader = new FileReader();
			reader.onload = E => {
				const xml = E.target.result;
				// 在bpmn实例中导入该本地文件
				this.modeler.importXML(xml, function (err) {
					if (err) {
						console.error(err);
					}
				});
			};
			reader.readAsText(this.fileList[0]);
		},
		// 下载
		setEncoded(name, data) {
			// 将xml或svg作为 URI 组件进行编码
			const encodedData = encodeURIComponent(data);
			// 创建a链接进行下载
			if (data) {
				const a = document.createElement("a");
				a.download = name;
				a.href = "data:application/bpmn20-xml;charset=UTF-8," + encodedData;
				document.body.appendChild(a);
				a.click();
				document.body.removeChild(a);
			}
		},
		// 下载bpmn
		saveDiagram() {
			this.modeler.saveXML({ format: true }, (err, xml) => {
				this.setEncoded("diagram.bpmn", err ? null : xml);
			});
		},
		// 下载svg
		saveSvg() {
			this.modeler.saveSVG((err, svg) => {
				this.setEncoded("diagram.svg", err ? null : svg);
			});
		},

		// 通过Id获取节点实例
		getBpmEl(id = "Task_1hcentk") {
			const elementRegistry = this.modeler.get("elementRegistry");
			const el = elementRegistry.get(id); // .getAll()获取全部节点
			console.log(el);
			// this.modeler.modeling.updateLabel('Task_1hcentk','123');
		},
		// 获取流程图内所有指定类型的节点
		getTastType(type = "bpmn:UserTask") {
			const elementRegistry = this.modeler.get("elementRegistry"); // 获取所有任务任务
			const taskList = elementRegistry.filter(item => item.type === type);
			return taskList;
		},
		// 改变节点颜色
		changeColor(el) {
			const modeling = this.modeler.get("modeling");
			modeling.setColor(el, {
				stroke: "green",
				fill: "yellow",
			});
		},
		clear() {
			this.modeler.clear();
		},
	},
};
</script>

<style lang="scss">
/*左边工具栏以及编辑节点的样式*/
@import "~bpmn-js/dist/assets/diagram-js.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";
/*右边工具栏样式*/
@import "~bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css";
@import "./custom/index.scss";

.buttons {
	position: absolute;
	bottom: 40px;
	left: 100px;
	padding: 0;
	margin: 0;
	list-style: none;
	& > li {
		display: inline-block;
		margin-right: 10px;
		& > a {
			background: #ddd;
			border: solid 1px #666;
			display: inline-block;
			padding: 5px;
			&.active {
				opacity: 1;
			}
		}
	}
}
.properties-panel-parent {
	width: 260px;
	border-left: 1px solid #ccc;
	overflow: auto;
	position: absolute;
	top: 21px;
	right: 0px;
	height: calc(100% - 40px);
	&:empty {
		display: none;
		&.djs-properties-panel {
			padding-bottom: 70px;
			min-height: 100%;
		}
	}
}

.containers {
	position: absolute;
	background-color: #ffffff;
	width: calc(100%);
	height: calc(100% - 40px);
}
.canvas {
	width: 100%;
	height: 100%;
}
.panel {
	position: absolute;
	right: 0;
	top: 0;
	width: 300px;
}

// svg修改样式
.addMarker-class .djs-visual > :nth-child(1) {
	stroke: #91d5ff !important; /* color elements as red */
	fill: #e6f7ff !important; /* color elements as red */
	fill-opacity: 0.5 !important;
}
</style>
